import java.math.RoundingMode;
import java.text.*;
import java.util.Date;
import java.util.Locale;

/**
 * 常用类之格式化
 * 参考:
 * https://yq.aliyun.com/articles/18479#
 * http://blog.csdn.net/gjb724332682/article/details/51768871
 * https://www.jianshu.com/p/5286a44ed9b1
 * http://www.cnblogs.com/chenssy/p/3366632.html
 */
public class FormatDemo {

    public static void main(String[] args) {
//        getDateFormat();       //格式化时间/日期
        getSimpleDateFormat(); //基本都用这个格式化时间和如期
//        getNumberFormat();     //数字格式化,￥44,444.51,4,444,451.23%和保留几个小数等
//        getFormatter();        //格式化文件大小,自动转换为KB, MB, GB
        getDecimalFormat();    //最强大的类,看看就行了,长知识
    }

    /**
     * DateFormat是日期格式化中最基本的方式
     * 实际应用开发中，使用最多的是SimpleDateFormat
     */
    private static void getDateFormat() throws ParseException {
        // 获取日期格式器，该格式器具有默认语言环境的默认格式化风格
        DateFormat dateFormat = DateFormat.getDateInstance();
        // 格式化当前时间
        System.out.println(dateFormat.format(new Date()));  //结果：2017-12-27
        // 解析字符串为时间
        System.out.println(dateFormat.parse("2015-12-26")); //结果：Sat Dec 26 00:00:00 CST 2015
        // 获取时间格式器，该格式器具有默认语言环境的默认格式化风格。
        DateFormat timeFormat = DateFormat.getTimeInstance();
        // 格式化当前时间
        System.out.println(timeFormat.format(new Date()));  //结果：14:02:59
        // 解析字符串为时间
        System.out.println(timeFormat.parse("21:40:02")); //结果：Thu Jan 01 21:40:02 CST 1970

        Date date = new Date();
        DateFormat dateFormat1 = DateFormat.getDateInstance(DateFormat.SHORT, Locale.CHINA);
        DateFormat dateFormat2 = DateFormat.getTimeInstance(DateFormat.SHORT, Locale.CHINA);
        DateFormat dateFormat3 = DateFormat.getDateTimeInstance(DateFormat.SHORT, DateFormat.SHORT, Locale.CHINA);
        System.out.println(dateFormat1.format(date)); //结果：16-7-5
        System.out.println(dateFormat2.format(date)); //结果：下午5:30
        System.out.println(dateFormat3.format(date)); //结果： 6-7-5 下午5:30

        DateFormat dateFormat4 = DateFormat.getDateInstance(DateFormat.MEDIUM, Locale.CHINA);
        DateFormat dateFormat5 = DateFormat.getTimeInstance(DateFormat.MEDIUM, Locale.CHINA);
        DateFormat dateFormat6 = DateFormat.getDateTimeInstance(DateFormat.LONG, DateFormat.LONG, Locale.CHINA);
        System.out.println(dateFormat4.format(date)); //结果： 2016-7-5
        System.out.println(dateFormat5.format(date)); //结果： 17:30:22
        System.out.println(dateFormat6.format(date)); //结果： 2016年7月5日 下午05时30分22秒

        System.out.println(dateFormat6.parse("2016年7月5日 下午05时29分54秒"));//结果：Tue Jul 05 17:29:54 CST 2016
    }

    /**
     * SimpleDateFormat是一个以与语言环境有关的方式来格式化和解析日期的具体类。
     * 它允许进行格式化（日期 -> 文本）、解析（文本 -> 日期）和规范化
     */
    private static void getSimpleDateFormat() {
        // 获得当前时间
        Date date = new Date();
        SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        // 格式化当前时间
        System.out.println(dateFormat.format(date)); //结果：2017-12-27 14:08:39
        // 解析
        try {
            System.out.println(dateFormat.parse("2015-12-26 22:04:55")); //结果：Sat Dec 26 22:04:55 CST 2015
        } catch (ParseException e) {
            e.printStackTrace();
        }
    }

    /**
     * NumberFormat是所有数值格式的抽象基类
     */
    private static void getNumberFormat() throws ParseException {
        double d = 44444.51234;
        //整数格式
        NumberFormat integer = NumberFormat.getIntegerInstance();
        System.out.println(integer.format(d)); //结果：44,445 支取整数,不取小数,默认分组

        //数值格式
        NumberFormat number = NumberFormat.getNumberInstance();
        number.setMinimumIntegerDigits(2); //设置整数部分至少为2位
        number.setMaximumIntegerDigits(3); //设置整数部分最多是3位
        number.setMinimumFractionDigits(3); //设置小数点后面至少3位
        number.setMaximumFractionDigits(4); //设置小数点后面最多是4位
        System.out.println(number.format(d));   //结果：444.5123

        number.setParseIntegerOnly(true);  //设置数是否应该仅作为整数进行解析
        number.setGroupingUsed(false);     //设置此格式中是否使用分组
        System.out.println(number.parse("10000000.001")); //结果：10000000

        // 货币格式
        NumberFormat currency = NumberFormat.getCurrencyInstance();
        currency.setMinimumFractionDigits(3); //小数点后面至少3位
        System.out.println(currency.format(d)); //结果：￥44,444.512 默认分组
        System.out.println(currency.parse("￥10,000.00"));//结果：10000

        //百分比格式
        NumberFormat percent = NumberFormat.getPercentInstance();
        percent.setMaximumFractionDigits(2); //小数点后面最多2位
        System.out.println(percent.format(d));  //结果：4,444,451.23% 默认分组
        System.out.println(percent.parse("100.1%"));//结果：1.001 默认可以解析小数
    }

    /**
     * Android,文件大小自动转化为KB, MB, GB
     */
    private static void getFormatter() {
//        Formatter.formatFileSize(this, Long.valueOf(123456)); //结果：121KB
//        Formatter.formatFileSize(this, Long.valueOf(12345612)); //结果： 11.77MB
//        Formatter.formatFileSize(this, Long.valueOf(1234561234)); //结果： 1.15GB
    }

    /**
     * DecimalFormat 是 NumberFormat 的一个具体子类，用于格式化十进制数字。
     * 常用于保留小数点后几位、数字间用,分割、四舍五入等场合。
     * 0：数字。如果当前位置不存在数字，则显示为0
     * .：小数分隔符或货币小数分隔符
     * #：数字。在不影响数值的情况下，当前位置如果为0或者不存在，则不显示
     * ,：数字。分组分隔符(只能放在整数部分)
     * -：缺省负数前缀。
     * %：前缀或后缀。乘以 100 并显示为百分数
     * \u2030 前缀或后缀。乘以 1000 并显示为千分数
     */
    private static void getDecimalFormat() {
        double d = 0.51;
//        DecimalFormat format1 = new DecimalFormat("00.000");
//        System.out.println(format1.format(d));  //结果：00.510
        customFormat("00.000",d);
//        DecimalFormat format2 = new DecimalFormat("#0.000");
//        System.out.println(format2.format(d));  //结果：0.510
        customFormat("#0.000",d);
//        DecimalFormat format3 = new DecimalFormat("0.###");
//        System.out.println(format3.format(d));  //结果：0.51
        customFormat("0.###",d);

        //（0）截取整数部分
        DecimalFormat df = new DecimalFormat("0");
        df.setRoundingMode(RoundingMode.HALF_DOWN);
        System.out.println(df.format(123.123));//结果：123
        System.out.println(df.format(123.0));//结果：123
        System.out.println(df.format(0.123));//结果：0

        //（0.）截取整数部分和小数点后一位
        DecimalFormat df1 = new DecimalFormat("0.0");
        df1.setRoundingMode(RoundingMode.HALF_DOWN);
        System.out.println(df1.format(123.123));//结果：123.1
        System.out.println(df1.format(123.0));//结果：123
        System.out.println(df1.format(0.123));//结果：0.1

        //（0.）截取整数部分（前两位没有时补0）和小数点后两位
        DecimalFormat df2 = new DecimalFormat("00.00");
        df2.setRoundingMode(RoundingMode.HALF_DOWN);
        System.out.println(df2.format(123.123));//结果：123.12
        System.out.println(df2.format(123.0));//结果：123.00
        System.out.println(df2.format(0.123));//结果：00.12

        //（#）截取整数部分
        DecimalFormat df3 = new DecimalFormat("#");
        df3.setRoundingMode(RoundingMode.HALF_DOWN);
        System.out.println(df3.format(123.123));//结果：123
        System.out.println(df3.format(123.0));//结果：123
        System.out.println(df3.format(0.123));//结果：0

        //（#.）截取整数部分和小数点后两位（小数部分为0时，不显示小数）
        DecimalFormat df4 = new DecimalFormat("##.##");
        df4.setRoundingMode(RoundingMode.HALF_DOWN);
        System.out.println(df4.format(123.125));//结果：123.12
        System.out.println(df4.format(123.0));//结果：123
        System.out.println(df4.format(0.123));//结果：0.12

        //（,#）整数部分每3位用,分隔
        DecimalFormat df5 = new DecimalFormat(",###");
        System.out.println(df5.format(123123123.123));//结果：123,123,123

        //（,#.0）整数部分每3位用,分隔、小数后两位（小数部分为0时显示.00）
        DecimalFormat df6 = new DecimalFormat(",###.00");
        System.out.println(df6.format(123123123.123));//结果：123,123,123.12
        System.out.println(df6.format(123.0));//结果：123.00
        System.out.println(df6.format(0.123));//结果：.12

        //（#.#%）以百分比显示，并保留小数点后一位
        DecimalFormat df7 = new DecimalFormat("#.#%");
        System.out.println(df7.format(123.123));//结果：12312.3%
        System.out.println(df7.format(123.0));//结果：12300%
        System.out.println(df7.format(0.123));//结果：12.3%

        //（-#）以负数显示
        DecimalFormat df8 = new DecimalFormat("-#");
        System.out.println(df8.format(123123123.123));//结果：-123123123
        System.out.println(df8.format(123.0));//结果：-123
        System.out.println(df8.format(0.123));//结果：-0

        //（#.字符）截取整数部分、保留一位小数、以字符串kg结尾
        DecimalFormat df9 = new DecimalFormat("#.# kg");
        System.out.println(df9.format(123.123));//结果：123.1 kg

        //（#字符）选择整数部分，以字符串千克结尾
        DecimalFormat df10 = new DecimalFormat("# 千克");
        System.out.println(df10.format(123123123.123));//结果：123123123 千克
        System.out.println(df10.format(123.0));//结果：123 千克
        System.out.println(df10.format(0.123));//结果：0 千克

        //四舍五入，保留小数点后一位
        DecimalFormat df11 = new DecimalFormat("#.#");
        df11.setRoundingMode(RoundingMode.HALF_UP);
        System.out.println(df11.format(123.15));//结果：123.2
        System.out.println(df11.format(123.14));//结果：123.1

        /**
         * 参考http://www.cnblogs.com/chenssy/p/3366632.html
         *  RoundingMode的介绍
         1、 ROUND_UP：只要舍弃位非0即进位。
         2、 ROUND_DOWN：不存在进位情况。
         3、 ROUND_CEILING：若是正数，舍入行为类似于ROUND_UP，若为负数，舍入行为类似于ROUND_DOWN。Math.round()方法就是使用的此模式。
         4、 ROUND_FLOOR：若是正数，舍入行为类似于ROUND_DOWN；若为负数，舍入行为类似于ROUND_UP。
         5、 HALF_UP：最近数字舍入(5进)。这是我们最经典的四舍五入。
         6、 HALF_DOWN：最近数字舍入(5舍)。在这里5是要舍弃的。
         7、 HAIL_EVEN：银行家舍入法。
         */

    }

    public static void customFormat(String pattern, double value) {
        DecimalFormat decimalFormat = new DecimalFormat(pattern);
        String output = decimalFormat.format(value);
        System.out.println("pattern=" + pattern+",value="+value+",output="+output);
        System.out.println("=======================");
    }

}
